package yl.hs.bmipfull.controllers.system;

import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.authentication.*;
import org.springframework.web.bind.annotation.*;
import yl.hs.bmipfull.controllers.ControllerBase;
import yl.hs.bmipfull.daos.salemanage.ILinkerInfoDao;
import yl.hs.bmipfull.exception.UserAccountException;
import yl.hs.bmipfull.pojo.salemanage.LinkerInfoEntity;
import yl.hs.bmipfull.pojo.system.AppSettingEntity;
import yl.hs.bmipfull.pojo.system.UserInfoEntity;
import yl.hs.bmipfull.pojo.system.WechatUserEntity;
import yl.hs.bmipfull.security.AuthenticationToken;
import yl.hs.bmipfull.security.MD5;
import yl.hs.bmipfull.security.SecurityUtils;
import yl.hs.bmipfull.service.salemanage.ICustomUserService;
import yl.hs.bmipfull.service.salemanage.ICustomerInfoService;
import yl.hs.bmipfull.service.system.IAppSettingService;
import yl.hs.bmipfull.service.system.IOrganizationInfoService;
import yl.hs.bmipfull.service.system.IUserService;
import yl.hs.bmipfull.service.system.IWechatUserService;
import yl.hs.bmipfull.utils.CK;
import yl.hs.bmipfull.utils.HsApp;
import yl.hs.bmipfull.utils.Tl;
import yl.hs.bmipfull.utils.datastate.ActionType;
import yl.hs.bmipfull.viewmodels.JHModel;
import yl.hs.bmipfull.viewmodels.LoginBean;
import yl.hs.bmipfull.viewmodels.WebResult;

import javax.servlet.RequestDispatcher;
import javax.servlet.http.HttpServletRequest;

/**
 * @author 谢景广
 * @category 用户登录Web接口
 */
@Api(value = "用户登录Web接口", tags = "系统管理——用户登录操作")
@RestController
public class LoginController extends ControllerBase {

    @Autowired
    IUserService userSvc;
    @Autowired
    IWechatUserService wechatUserService;

    @Autowired
    IOrganizationInfoService orgSvc;

    @Autowired
    ICustomUserService customUserSvc;

    @Autowired
    ILinkerInfoDao linkerInfoDao;

    @Autowired
    private AuthenticationManager authenticationManager;

    @Autowired
    IAppSettingService appSetSvc;

    /**
     * 用户登录
     *
     * @param loginBean 登录信息
     * @return web响应结果
     */
    @RequestMapping(value = "/login", method = RequestMethod.POST)
    @ApiOperation(value = "用户登录", notes = "根据用户提交的租户代码，用户账户和用户密码登陆系统")
    @ResponseBody
    public WebResult login(@RequestBody LoginBean loginBean, HttpServletRequest request) {
        try {
            AuthenticationToken token = SecurityUtils.login(request, loginBean.getAccount(), loginBean.getPassword(), authenticationManager);
            var user = userSvc.findUserByAccount(token.getName());
            if (user != null) {
                if (!Tl.isEmpty(loginBean.getPhoneCode())) {
                    user.setPhoneCode(loginBean.getPhoneCode());
                    userSvc.updateUserInfo(user);
                }
                var company = orgSvc.findBySn(user.getCompanySN());
                var login = HsApp.addCurrent(user, company.getFullName());
                if (HsApp.checkSystem()) {
                    appSetSvc.querySetObjByUnitSn(user.getOrganizationCode().split(","));
                }

                userSvc.writeLog(ActionType.LOGIN, user.getSn(), String.format("用户%s登录", loginBean.getAccount()), "", null);
                return success("ok", login, token.getToken());
            } else {
                var msg = "没有此用户";
                userSvc.writeLog(ActionType.LOGIN, "", String.format("用户%s尝试登录:%s", loginBean.getAccount(), msg), "", null);
                return fail(msg);
            }
        } catch (AccountStatusException ee) {
            var message = "";
            if (ee instanceof LockedException) {
                message = "用户账户已锁定，请联系管理员";
            }
            if (ee instanceof DisabledException) {
                message = "用户账户已禁用，请联系管理员";
            }
            if (ee instanceof AccountExpiredException) {
                message = "用户账户已过期，请联系管理员";
            }
            if (ee instanceof CredentialsExpiredException) {
                message = "用户密码已过期，请联系管理员";
            }
            return fail(message);
        } catch (UserAccountException ex) {
            userSvc.writeLog(ActionType.LOGIN, "", String.format("用户%s尝试登录:%s", loginBean.getAccount(), ex.getMessage()), "", null);
            return fail(ex.getMessage());
        } catch (Exception ee) {
            userSvc.writeLog(ActionType.LOGIN, "", String.format("用户%s尝试登录:%s", loginBean.getAccount(), ee.getMessage()), "", null);
            if (ee instanceof BadCredentialsException) {
                return fail("用户名或密码错误");
            }
            return error(ee);
        }
    }

    @RequestMapping(value = "/construction/login", method = RequestMethod.POST)
    @ApiOperation(value = "工地用户登录", notes = "根据用户提交的租户代码，用户账户和用户密码登陆系统")
    @ResponseBody
    public WebResult projectLogin(@RequestBody LoginBean loginBean, HttpServletRequest request) {
        try {
            AuthenticationToken token = SecurityUtils.login(request, loginBean.getAccount(), loginBean.getPassword(), authenticationManager);
            var user = linkerInfoDao.findUserByAccount(token.getName());
            if (user != null) {
                var customerUser = customUserSvc.findByCustSNAndLinkSN(user.getSn(), user.getCustSn());
                if (customerUser == null) {
                    return fail("用户不允许登录！");
                }
                var nUser = new UserInfoEntity();
                if (!Tl.isEmpty(loginBean.getPhoneCode())) {
                    user.setPhoneCode(loginBean.getPhoneCode());
                    linkerInfoDao.update(user);
                }

                nUser.setSn(user.getSn());
                nUser.setCompanySN(user.getCustSn());
                var customer = customSvc.findBySN(user.getCustSn());
                if (customer != null) {
                    nUser.setOrganizationCode(customer.getOrganizationCode());
                }
                nUser.setAccount(token.getName());
                nUser.setMobileNum(token.getName());
                nUser.setRealname(user.getFullName());
                nUser.setGender(user.isGender());
                nUser.setNickname(user.getFullName());
                nUser.setQqNum(user.getQq());
                nUser.setEmail(user.getEmail());
                nUser.setState((short) 1);
                nUser.setUseLanguage("");
                nUser.setTheme("");
                nUser.setImageSN("");
                HsApp.addCurrent(nUser, user.getCompanyName());
                userSvc.writeLog(ActionType.LOGIN, user.getSn(), String.format("用户%s登录", loginBean.getAccount()), "", null);
                return success(nUser.toString(), nUser, token.getToken(), false);
            } else {
                var msg = "没有此用户";
                userSvc.writeLog(ActionType.LOGIN, "", String.format("用户%s尝试登录:%s", loginBean.getAccount(), msg), "", null);
                return fail(msg);
            }
        } catch (AccountStatusException ee) {
            var message = "";
            if (ee instanceof LockedException) {
                message = "用户账户已锁定，请联系管理员";
            }
            if (ee instanceof DisabledException) {
                message = "用户账户已禁用，请联系管理员";
            }
            if (ee instanceof AccountExpiredException) {
                message = "用户账户已过期，请联系管理员";
            }
            if (ee instanceof CredentialsExpiredException) {
                message = "用户密码已过期，请联系管理员";
            }
            return fail(message);
        } catch (UserAccountException ex) {
            userSvc.writeLog(ActionType.LOGIN, "", String.format("用户%s尝试登录:%s", loginBean.getAccount(), ex.getMessage()), "", null);
            return fail(ex.getMessage());
        } catch (Exception ee) {
            userSvc.writeLog(ActionType.LOGIN, "", String.format("用户%s尝试登录:%s", loginBean.getAccount(), ee.getMessage()), "", null);
            if (ee instanceof BadCredentialsException) {
                return fail("用户名或密码错误");
            }
            return error(ee);
        }
    }

    @RequestMapping(value = "/construction/WechatLogin", method = RequestMethod.POST)
    @ApiOperation(value = "工地用户登录", notes = "根据用户提交的租户代码，用户账户和用户密码登陆系统")
    @ResponseBody
    public WebResult WechatProjectLogin(@RequestBody LoginBean loginBean, HttpServletRequest request) {
        try {
            LinkerInfoEntity user = null;
            AuthenticationToken token = null;
            if (loginBean.getOpenid() != null) {
                var linker = linkerInfoDao.getByOpenid(loginBean.getOpenid());

                if (linker != null) {
                    var customerUser = customUserSvc.findByCustSNAndLinkSN(linker.getSn(), linker.getCustSn());
                    if (customerUser == null) {
                        return fail("用户不允许登录！");
                    }
                    token = SecurityUtils.login(request, linker.getMobilePhone(), linker.getRealPassword(), authenticationManager);
                    user = linker;
                } else {
                    if (loginBean.getAccount() == null) {
                        var msg = "微信用户验证失败";
                        userSvc.writeLog(ActionType.LOGIN, "", String.format("用户%s尝试登录:%s", loginBean.getAccount(), msg), "", null);
                        return fail(msg);
                    }
                    token = SecurityUtils.login(request, loginBean.getAccount(), loginBean.getPassword(), authenticationManager);
                    user = linkerInfoDao.findUserByAccount(token.getName());
                    if (user != null) {
                        WechatUserEntity weChatUser = new WechatUserEntity();
                        weChatUser.setOpenId(loginBean.getOpenid());
                        weChatUser.setCustomerName(user.getCustomerName());
                        weChatUser.setCustomerSN(user.getCustSn());
                        weChatUser.setMobilePhone(user.getMobilePhone());
                        weChatUser.setUserName(user.getFullName());
                        weChatUser.setUserState(user.getState());
                        var weChatUserMap = weChatUser.toMap();
                        weChatUserMap.put("companyid", loginBean.getCompanyid());
                        wechatUserService.saveProjectWechatUser(weChatUserMap, null);
                    }
                }
                if (user != null) {
                    user.setOpenid(loginBean.getOpenid());
                    linkerInfoDao.update(user);
                    var nUser = new UserInfoEntity();
                    if (!Tl.isEmpty(loginBean.getPhoneCode())) {
                        user.setPhoneCode(loginBean.getPhoneCode());
                        linkerInfoDao.update(user);
                    }

                    nUser.setSn(user.getSn());
                    nUser.setCompanySN(user.getCustSn());
                    var customer = customSvc.findBySN(user.getCustSn());
                    if (customer != null) {
                        nUser.setOrganizationCode(customer.getOrganizationCode());
                    }
                    nUser.setAccount(token.getName());
                    nUser.setMobileNum(token.getName());
                    nUser.setRealname(user.getFullName());
                    nUser.setGender(user.isGender());
                    nUser.setNickname(user.getFullName());
                    nUser.setQqNum(user.getQq());
                    nUser.setEmail(user.getEmail());
                    nUser.setState((short) 1);
                    nUser.setUseLanguage("");
                    nUser.setTheme("");
                    nUser.setImageSN("");
                    HsApp.addCurrent(nUser, user.getCompanyName());
                    userSvc.writeLog(ActionType.LOGIN, user.getSn(), String.format("用户%s登录", loginBean.getAccount()), "", null);
                    return success(nUser.toString(), nUser, token.getToken(), false);
                } else {
                    var msg = "没有此用户";
                    userSvc.writeLog(ActionType.LOGIN, "", String.format("用户%s尝试登录:%s", loginBean.getAccount(), msg), "", null);
                    return fail(msg);
                }
            } else {
                var msg = "微信用户验证失败";
                userSvc.writeLog(ActionType.LOGIN, "", String.format("用户%s尝试登录:%s", loginBean.getAccount(), msg), "", null);
                return fail(msg);
            }

        } catch (AccountStatusException ee) {
            var message = "";
            if (ee instanceof LockedException) {
                message = "用户账户已锁定，请联系管理员";
            }
            if (ee instanceof DisabledException) {
                message = "用户账户已禁用，请联系管理员";
            }
            if (ee instanceof AccountExpiredException) {
                message = "用户账户已过期，请联系管理员";
            }
            if (ee instanceof CredentialsExpiredException) {
                message = "用户密码已过期，请联系管理员";
            }
            return fail(message);
        } catch (UserAccountException ex) {
            userSvc.writeLog(ActionType.LOGIN, "", String.format("用户%s尝试登录:%s", loginBean.getAccount(), ex.getMessage()), "", null);
            return fail(ex.getMessage());
        } catch (Exception ee) {
            userSvc.writeLog(ActionType.LOGIN, "", String.format("用户%s尝试登录:%s", loginBean.getAccount(), ee.getMessage()), "", null);
            if (ee instanceof BadCredentialsException) {
                return fail("用户名或密码错误");
            }
            return error(ee);
        }
    }

    /**
     * @return web响应结果
     * @category 用户退出
     */
    @RequestMapping(value = "/logout", method = RequestMethod.DELETE)
    @ApiOperation(value = "用户退出", notes = "用户主动退出系统登录")
    @ResponseBody
    public WebResult logout() {
        HsApp.removeCurrent();
        return success("ok");
    }

    /**
     * @return web响应结果
     * @category 错误处理
     */
    @RequestMapping(value = "/error", method = RequestMethod.GET)
    @ResponseBody
    public WebResult error(HttpServletRequest request) {

        Integer statusCode = (Integer) request.getAttribute(RequestDispatcher.ERROR_STATUS_CODE);
        return new WebResult(statusCode);
    }

    /**
     * @return web响应结果
     * @category 错误处理
     */
    @ApiOperation(value = "获取初始化状态", notes = "系统初始化")
    @RequestMapping(value = "/systemIsInit", method = RequestMethod.GET)
    @ResponseBody
    public WebResult systemInit() {
        try {
            return success("ok", orgSvc.checkOrgIsEmpty());
        } catch (Exception ee) {
            return error(ee);
        }
    }


    /**
     * @return web响应结果
     * @category 错误处理
     */
    @ApiOperation(value = "保存初始化信息", notes = "系统初始化")
    @RequestMapping(value = "/saveInit", method = RequestMethod.POST)
    public WebResult saveInit(@RequestBody JHModel model) {
        try {
            var result = orgSvc.createRootInit(model.getOrgName());
            var org = orgSvc.findRootUnit();
            var stVers = appSetSvc.findByCode(CK.SysVersion, org.getSn());
            if (stVers == null) {
                stVers = new AppSettingEntity();
                stVers.setParamName("系统版本");
                stVers.setParamCode(CK.SysVersion);
                stVers.setParamValue(CK.getVersionCode(model.getVersionName()));
                stVers.setOrganizationSN(org.getSn());
                appSetSvc.save(stVers);
            } else {
                stVers.setParamValue(model.getVersion());
                appSetSvc.save(stVers);
            }

            var stUser = appSetSvc.findByCode(CK.Service_User, org.getSn());
            if (stUser == null) {
                stUser = new AppSettingEntity();
                stUser.setParamName("服务人员");
                stUser.setParamCode(CK.Service_User);
                stUser.setParamValue(model.getServiceUser());
                stUser.setOrganizationSN(org.getSn());
                appSetSvc.save(stUser);
            } else {
                stUser.setParamValue(model.getServiceUser());
                appSetSvc.save(stUser);
            }
            var stVerName = appSetSvc.findByCode(CK.SysVersionName, org.getSn());
            if (stVerName == null) {
                stVerName = new AppSettingEntity();
                stVerName.setParamName("系统版本名称");
                stVerName.setParamCode(CK.SysVersionName);
                stVerName.setParamValue(model.getVersionName());
                stVerName.setOrganizationSN(org.getSn());
                appSetSvc.save(stVerName);
            } else {
                stVerName.setParamValue(model.getVersion());
                appSetSvc.save(stVerName);
            }
            return success("ok", result > 0);
        } catch (Exception ee) {
            return error(ee);
        }
    }

    @Autowired
    ICustomerInfoService customSvc;
}
